#ifndef ZPCIEDEVICE_HPP
#define ZPCIEDEVICE_HPP

#include "ZViewDevice.hpp"
#include "zviewctl.h"
#include <cstdint>
#include <initializer_list>
#include <thread>   
#include <condition_variable>
#include <atomic>
#include <functional>
#include <map>
#include <mutex>
#include <set>
#include <unistd.h>
#include <sys/eventfd.h>
#include <list>
class  ZPCIeDevice:public CZViewDevice
{
private:
    int                         m_fd{-1};       //设备句柄
    zview_device_info           m_iZViewDevInfo;     //PCI信息
    zview_device_int_table      m_iIntTable;    //中断列表
    zview_device_memory_info    m_iMemInfo;     //设备内存信息
    void*                       m_arrMemAddr[6] ;   //设备映射地址

    bool                        m_bMapUsed{false};     //使用内存映射

    std::thread                   m_thdInt;               //Interrupt Thread
    std::atomic<bool>             m_bMonitorInt{false};
    std::recursive_mutex          m_mutexInterrupt;
    std::multimap<zview_interrupt_id,int>           m_mapInterruptEventFds;      //interrupt events

    std::thread                   m_thdDma;               //Interrupt Thread
    std::atomic<bool>             m_bMonitorDma{false};
    std::recursive_mutex          m_mutexDma;
    std::list<std::pair<zview_device_dma_transaction,std::function<void(uint64_t)>>>             m_listDmaEventFds;      //interrupt events

public:
     ZPCIeDevice(const DeviceInfo& info);
    ~ZPCIeDevice();

public:
    bool Open() override;
    bool IsOpen() override;
    bool Close() override;
    
    //映射读写
    bool Write(uint8_t bar,uint32_t offset,const void* data,uint32_t len) override;
    bool Read(uint8_t bar,uint32_t offset, void* data,uint32_t len) override;
    bool MapMem(const std::initializer_list<uint8_t>& list) override;
    void* GetMapMemAddr(uint8_t bar) override;
    void UseMap(bool used) override;      //是否使用mmap映射 ，这会导致更多的内存占用

    //DMA相关
    bool DmaH2C (void *dst, void *src, size_t size) override;
    bool DmaC2H(void* dst,void* src,size_t size) override;
    bool DmaH2CAsyn(void* dst,void*src,uint32_t size,std::function<void(uint64_t)>callback) override;  //异步执行DMA,该函数立即返回,回调函数参数为返回结果,注意回调函数应当能快速执行完毕
    bool DmaC2HAsyn(void* dst,void*src,uint32_t size,std::function<void(uint64_t)>callback) override;

    //中断相关
    int WaitInt(zview_interrupt_id interrupt_code,uint32_t timeout) override;       //同步阻塞等待中断
    bool GetInrTable(zview_device_int_table& int_table) override;
    uint64_t GetInrMask()  const override; 
    int  GetDeviceFd ()  const override;
private:
    bool MonitorInt();
    void StartMontiorIntThd();
    void StopMontiorIntThd();

    bool MonitorDmaAsyn();
    void StartMonitorDmaThd();
    void StopMontiorDmaThd();
    void InsertDmaTransaction(zview_device_dma_transaction trans,std::function<void(uint64_t)> callback);

    bool MapBar(uint8_t bar);
    bool UnmapBar(uint8_t bar);
    void ClearMapBar();
    uint8_t GetBarCount();
    bool InitPciInfo();

};








#endif // ZPCIEDEVICE_HPP
